Week 13 of 16

Watch: Async Fundamentals

Understand how Python can do many things at once — and why that matters for API calls.

Day 61 60 minutes Watch

Day 61 of 80

Why Async Matters for You

Right now, when you generate prompts for 3 platforms, your code does this:

  1. Call Claude for Kling → wait 2 seconds → get result
  2. Call Claude for Runway → wait 2 seconds → get result
  3. Call Claude for Veo → wait 2 seconds → get result
  4. Total: ~6 seconds

With async, it does this:

  1. Start all 3 calls simultaneously
  2. Wait for all 3 to finish
  3. Total: ~2 seconds

Same work, 3x faster. For batch generation (20 shots × 3 platforms = 60 API calls), the difference is minutes vs. seconds.

The Mental Model: The Restaurant Waiter

Synchronous waiter: Takes table 1's order → walks to kitchen → waits for food → brings it back → walks to table 2. Takes table 2's order → walks to kitchen → waits for food → brings it back. Customers at table 2 wait for the whole cycle.

Async waiter: Takes table 1's order → sends it to kitchen → takes table 2's order → sends it → takes table 3's order → sends it → brings food to tables as it comes out. Kitchen is doing the slow work. The waiter (your Python code) never just stands around waiting.

One waiter. Same kitchens. But the waiter never blocks — it moves to the next task whenever it's waiting on something else. That's async.

Watch

Video: Corey Schafer — Asyncio Tutorial (~45 min)

Python Asyncio Tutorial — Corey Schafer. The definitive Python asyncio tutorial. Type along with every example.

What to pay attention to:

Also Read (Optional)

Real Python — Async IO in Python — skim the first half for conceptual understanding. The analogy in this article (chess grandmaster vs. amateur players) is one of the clearest explanations of async I've seen.

Key Concepts to Lock In

async def and await

async def defines a coroutine — a function that can pause and resume. await is the pause point. When Python hits await, it pauses that coroutine and runs other ready coroutines until the awaited thing completes.

# Regular function — can't pause, blocks everything
def regular():
    result = slow_operation()  # blocks for 2 seconds
    return result

# Async function — can pause at 'await', lets other things run
async def async_version():
    result = await slow_operation()  # pauses here, but doesn't block other tasks
    return result
asyncio.gather() — the pattern you'll use most
import asyncio

async def main():
    # Run three things in parallel. gather() starts them all,
    # then waits for all to finish and returns all results.
    results = await asyncio.gather(
        task_one(),
        task_two(),
        task_three(),
    )
    # results is a list: [result_of_one, result_of_two, result_of_three]
    # They're in the same order as you passed them in.
    return results

asyncio.run(main())  # starts the async event loop
The AsyncAnthropic client

The Anthropic SDK has an async version of the client. Same API, but every method call needs await:

# Sync (one at a time):
client = anthropic.Anthropic()
message = client.messages.create(...)  # blocks

# Async (can run in parallel):
client = anthropic.AsyncAnthropic()
message = await client.messages.create(...)  # pauses without blocking
What Async Doesn't Do

Async doesn't make CPU-bound work faster. If you're doing heavy computation (image processing, math), asyncio won't help — you'd need threads or multiprocessing for that.

Async only helps with I/O-bound work — things where Python is waiting on something external: network requests, file reads, database queries. API calls are the perfect use case.

End of Day Checklist

Tomorrow

Day 62 experiments with async code in Jupyter — including your first parallel Claude API calls. You'll see the speed difference directly.